home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / programming / aros / devs / ram_handler.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-13  |  37.1 KB  |  1,519 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: ram_handler.c,v 1.3 1996/09/13 17:57:05 digulla Exp $
  4.     $Log: ram_handler.c,v $
  5.     Revision 1.3  1996/09/13 17:57:05  digulla
  6.     Use IPTR
  7.  
  8.     Revision 1.2  1996/09/12 14:52:01  digulla
  9.     Use correct way to access external names (was missing)
  10.  
  11.     Revision 1.1  1996/09/11 12:52:53  digulla
  12.     Two new devices by M. Fleischer: RAM: and NIL:
  13.  
  14.     Desc:
  15.     Lang:
  16. */
  17. #include <exec/errors.h>
  18. #include <exec/types.h>
  19. #include <exec/resident.h>
  20. #include <exec/memory.h>
  21. #include <exec/semaphores.h>
  22. #include <clib/exec_protos.h>
  23. #include <utility/tagitem.h>
  24. #include <clib/utility_protos.h>
  25. #include <dos/dosextens.h>
  26. #include <dos/dosasl.h>
  27. #include <dos/exall.h>
  28. #include <dos/filesystem.h>
  29. #include <clib/dos_protos.h>
  30. #include <aros/libcall.h>
  31. #ifdef __GNUC__
  32.     #include "ram_handler_gcc.h"
  33. #endif
  34. #include "machine.h"
  35.  
  36. #define NEWLIST(l)                          \
  37. ((l)->lh_Head=(struct Node *)&(l)->lh_Tail, \
  38.  (l)->lh_Tail=NULL,                         \
  39.  (l)->lh_TailPred=(struct Node *)(l))
  40.  
  41. extern const char name[];
  42. extern const char version[];
  43. extern const APTR inittabl[4];
  44. extern void *const functable[];
  45. extern const UBYTE datatable;
  46. extern struct rambase *__AROS_SLIB_ENTRY(init,ramdev)();
  47. extern void __AROS_SLIB_ENTRY(open,ramdev)();
  48. extern BPTR __AROS_SLIB_ENTRY(close,ramdev)();
  49. extern BPTR __AROS_SLIB_ENTRY(expunge,ramdev)();
  50. extern int __AROS_SLIB_ENTRY(null,ramdev)();
  51. extern void __AROS_SLIB_ENTRY(beginio,ramdev)();
  52. extern LONG __AROS_SLIB_ENTRY(abortio,ramdev)();
  53. extern void deventry();
  54. extern const char end;
  55.  
  56. /* Device node */
  57. struct cnode
  58. {
  59.     struct MinNode node;
  60.     LONG type;            /* ST_LINKDIR */
  61.     char *name;         /* Link's name */
  62.     struct cnode *self;     /* Pointer to top of structure */
  63.     struct hnode *link;     /* NULL */
  64.     LONG usecount;        /* >0 usecount locked:+(~0ul/2+1) */
  65.     ULONG protect;        /* 0 */
  66.     char *comment;        /* NULL */
  67.     struct vnode *volume;    /* Pointer to volume */
  68.     struct DosList *doslist;    /* Pointer to doslist entry */
  69. };
  70.  
  71. /* Volume node */
  72. struct vnode
  73. {
  74.     struct MinNode node;
  75.     LONG type;            /* ST_USERDIR */
  76.     char *name;         /* Directory name */
  77.     struct vnode *self;     /* Points to top of structure */
  78.     struct hnode *link;     /* This one is linked to me */
  79.     LONG usecount;        /* >0 usecount locked:+(~0ul/2+1) */
  80.     ULONG protect;        /* 0 */
  81.     char *comment;        /* NULL */
  82.     struct MinList list;    /* Contents of directory */
  83.     ULONG volcount;        /* number of handles on this volume */
  84.     struct DosList *doslist;    /* Pointer to doslist entry */
  85. };
  86.  
  87. /* Directory node */
  88. struct dnode
  89. {
  90.     struct MinNode node;
  91.     LONG type;            /* ST_USERDIR */
  92.     char *name;         /* Directory name */
  93.     struct vnode *volume;    /* Volume's root directory */
  94.     struct hnode *link;     /* This one is linked to me */
  95.     LONG usecount;        /* >0 usecount locked:+(~0ul/2+1) */
  96.     ULONG protect;        /* protection bits */
  97.     char *comment;        /* Some comment */
  98.     struct MinList list;    /* Contents of directory */
  99. };
  100.  
  101. /* File node */
  102. struct fnode
  103. {
  104.     struct MinNode node;
  105.     LONG type;            /* ST_FILE */
  106.     char *name;         /* Filename */
  107.     struct vnode *volume;    /* Volume's root directory */
  108.     struct hnode *link;     /* This one is linked to me */
  109.     LONG usecount;        /* >0 usecount locked:+(~0ul/2+1) */
  110.     ULONG protect;        /* protection bits */
  111.     char *comment;        /* Some file comment */
  112.     LONG size;            /* Filesize */
  113.     UBYTE *blocks[16];        /* Upto 0x1000 bytes */
  114.     UBYTE **iblocks[4];     /* Upto 0x41000 bytes */
  115.     UBYTE ***i2block;        /* Upto 0x1041000 bytes */
  116.     UBYTE ****i3block;        /* Upto 0x101041000 bytes */
  117. };
  118.  
  119. /* Softlink node */
  120. struct snode
  121. {
  122.     struct MinNode node;
  123.     LONG type;            /* ST_SOFTLINK */
  124.     char *name;         /* Link's name */
  125.     struct vnode *volume;    /* Volume's root directory */
  126.     struct hnode *link;     /* This one is hardlinked to me */
  127.     LONG usecount;        /* >0 usecount locked:+(~0ul/2+1) */
  128.     ULONG protect;        /* protection bits */
  129.     char *comment;        /* Some file comment */
  130.     char *contents;        /* Contents of soft link */
  131. };
  132.  
  133. /* Hardlink node */
  134. struct hnode
  135. {
  136.     struct MinNode node;
  137.     LONG type;            /* ST_LINKDIR */
  138.     char *name;         /* Link's name */
  139.     struct vnode *volume;    /* Volume's root directory */
  140.     struct hnode *link;     /* This one is hardlinked to me */
  141.     LONG usecount;        /* >0 usecount locked:+(~0ul/2+1) */
  142.     ULONG protect;        /* protection bits */
  143.     char *comment;        /* Some file comment */
  144.     struct hnode *orig;     /* original object */
  145. };
  146.  
  147. #define BLOCKSIZE    256
  148. #define PBLOCKSIZE    (256*sizeof(UBYTE *))
  149.  
  150. struct filehandle
  151. {
  152.     struct dnode *node;
  153.     IPTR position;
  154. };
  155.  
  156. int entry(void)
  157. {
  158.     /* If the device was executed by accident return error code. */
  159.     return -1;
  160. }
  161.  
  162. const struct Resident resident=
  163. {
  164.     RTC_MATCHWORD,
  165.     (struct Resident *)&resident,
  166.     (APTR)&end,
  167.     RTF_AUTOINIT,
  168.     1,
  169.     NT_LIBRARY,
  170.     0,
  171.     (char *)name,
  172.     (char *)&version[6],
  173.     (ULONG *)inittabl
  174. };
  175.  
  176. const char name[]="ram.handler";
  177.  
  178. const char version[]="$VER: ram handler 1.0 (28.3.96)\n\015";
  179.  
  180. const APTR inittabl[4]=
  181. {
  182.     (APTR)sizeof(struct rambase),
  183.     (APTR)functable,
  184.     (APTR)&datatable,
  185.     &__AROS_SLIB_ENTRY(init,ramdev)
  186. };
  187.  
  188. void *const functable[]=
  189. {
  190.     &__AROS_SLIB_ENTRY(open,ramdev),
  191.     &__AROS_SLIB_ENTRY(close,ramdev),
  192.     &__AROS_SLIB_ENTRY(expunge,ramdev),
  193.     &__AROS_SLIB_ENTRY(null,ramdev),
  194.     &__AROS_SLIB_ENTRY(beginio,ramdev),
  195.     &__AROS_SLIB_ENTRY(abortio,ramdev),
  196.     (void *)-1
  197. };
  198.  
  199. const UBYTE datatable=0;
  200.  
  201. __AROS_LH2(struct rambase *, init,
  202.  __AROS_LHA(struct rambase *, rambase, D0),
  203.  __AROS_LHA(BPTR,             segList,   A0),
  204.        struct ExecBase *, SysBase, 0, ramdev)
  205. {
  206.     __AROS_FUNC_INIT
  207.  
  208.     /* This function is single-threaded by exec by calling Forbid. */
  209.  
  210.     struct MsgPort *port;
  211.     struct Task *task;
  212.     struct SignalSemaphore *semaphore;
  213.     APTR stack;
  214.  
  215.     /* Store arguments */
  216.     rambase->sysbase=SysBase;
  217.     rambase->seglist=segList;
  218.     NEWLIST((struct List *)&rambase->waitdoslist);
  219.     rambase->dosbase=(struct DosLibrary *)OpenLibrary("dos.library",39);
  220.     if(rambase->dosbase!=NULL)
  221.     {
  222.     rambase->utilitybase=(struct UtilityBase *)OpenLibrary("utility.library",39);
  223.     if(rambase->utilitybase!=NULL)
  224.     {
  225.         port=(struct MsgPort *)AllocMem(sizeof(struct MsgPort),MEMF_PUBLIC|MEMF_CLEAR);
  226.         if(port!=NULL)
  227.         {
  228.         rambase->port=port;
  229.         NEWLIST(&port->mp_MsgList);
  230.         port->mp_Node.ln_Type=NT_MSGPORT;
  231.         port->mp_SigBit=SIGB_SINGLE;
  232.  
  233.         task=(struct Task *)AllocMem(sizeof(struct Task),MEMF_PUBLIC|MEMF_CLEAR);
  234.         if(task!=NULL)
  235.         {
  236.             port->mp_SigTask=task;
  237.             port->mp_Flags=PA_IGNORE;
  238.             NEWLIST(&task->tc_MemEntry);
  239.             task->tc_Node.ln_Type=NT_TASK;
  240.             task->tc_Node.ln_Name="ram.handler task";
  241.  
  242.             stack=AllocMem(2048,MEMF_PUBLIC);
  243.             if(stack!=NULL)
  244.             {
  245.             task->tc_SPLower=stack;
  246.             task->tc_SPUpper=(BYTE *)stack+2048;
  247. #if STACK_GROWS_DOWNWARDS
  248.             task->tc_SPReg=(BYTE *)task->tc_SPUpper-SP_OFFSET-sizeof(APTR);
  249.             ((APTR *)task->tc_SPUpper)[-1]=rambase;
  250. #else
  251.             task->tc_SPReg=(BYTE *)task->tc_SPLower-SP_OFFSET+sizeof(APTR);
  252.             *(APTR *)task->tc_SPLower=rambase;
  253. #endif
  254.  
  255.             semaphore=(struct SignalSemaphore *)AllocMem(sizeof(struct SignalSemaphore),MEMF_PUBLIC|MEMF_CLEAR);
  256.             if(semaphore!=NULL)
  257.             {
  258.                 rambase->sigsem=semaphore;
  259.                 InitSemaphore(semaphore);
  260.  
  261.                 if(AddTask(task,deventry,NULL)!=NULL)
  262.                 return rambase;
  263.  
  264.                 FreeMem(semaphore,sizeof(struct SignalSemaphore));
  265.             }
  266.             FreeMem(stack,2048);
  267.             }
  268.             FreeMem(task,sizeof(struct Task));
  269.         }
  270.         FreeMem(port,sizeof(struct MsgPort));
  271.         }
  272.         CloseLibrary((struct Library *)rambase->utilitybase);
  273.     }
  274.     CloseLibrary((struct Library *)rambase->dosbase);
  275.     }
  276.  
  277.     return NULL;
  278.     __AROS_FUNC_EXIT
  279. }
  280.  
  281. /* Use This from now on */
  282. #ifdef SysBase
  283.     #undef SysBase
  284. #endif
  285. #ifdef DOSBase
  286.     #undef DOSBase
  287. #endif
  288. #ifdef UtilityBase
  289.     #undef UtilityBase
  290. #endif
  291. #define SysBase rambase->sysbase
  292. #define DOSBase rambase->dosbase
  293. #define UtilityBase rambase->utilitybase
  294.  
  295. __AROS_LH3(void, open,
  296.  __AROS_LHA(struct IOFileSys *, iofs, A1),
  297.  __AROS_LHA(ULONG,              unitnum, D0),
  298.  __AROS_LHA(ULONG,              flags, D0),
  299.        struct rambase *, rambase, 1, ramdev)
  300. {
  301.     __AROS_FUNC_INIT
  302.     /*
  303.     This function is single-threaded by exec by calling Forbid.
  304.     If you break the Forbid() another task may enter this function
  305.     at the same time. Take care.
  306.     */
  307.  
  308.     /* Keep compiler happy */
  309.     unitnum=0;
  310.     flags=0;
  311.  
  312.     /* I have one more opener. */
  313.     rambase->device.dd_Library.lib_OpenCnt++;
  314.     rambase->device.dd_Library.lib_Flags&=~LIBF_DELEXP;
  315.  
  316.     /* Set returncode */
  317.     iofs->IOFS.io_Error=0;
  318.  
  319.     /* Mark Message as recently used. */
  320.     iofs->IOFS.io_Message.mn_Node.ln_Type=NT_REPLYMSG;
  321.     __AROS_FUNC_EXIT
  322. }
  323.  
  324. __AROS_LH1(BPTR, close,
  325.  __AROS_LHA(struct IOFileSys *, iofs, A1),
  326.        struct rambase *, rambase, 2, ramdev)
  327. {
  328.     __AROS_FUNC_INIT
  329.     /*
  330.     This function is single-threaded by exec by calling Forbid.
  331.     If you break the Forbid() another task may enter this function
  332.     at the same time. Take care.
  333.     */
  334.  
  335.     /* Let any following attemps to use the device crash hard. */
  336.     iofs->IOFS.io_Device=(struct Device *)-1;
  337.  
  338.     /* I have one fewer opener. */
  339.     if(!--rambase->device.dd_Library.lib_OpenCnt)
  340.     {
  341.     /* Delayed expunge pending? */
  342.     if(rambase->device.dd_Library.lib_Flags&LIBF_DELEXP)
  343.         /* Then expunge the device */
  344.         return expunge();
  345.     }
  346.     return 0;
  347.     __AROS_FUNC_EXIT
  348. }
  349.  
  350. __AROS_LH0(BPTR, expunge, struct rambase *, rambase, 3, ramdev)
  351. {
  352.     __AROS_FUNC_INIT
  353.  
  354.     BPTR ret;
  355.     /*
  356.     This function is single-threaded by exec by calling Forbid.
  357.     Never break the Forbid() or strange things might happen.
  358.     */
  359.  
  360.     /* Test for openers. */
  361.     if(rambase->device.dd_Library.lib_OpenCnt)
  362.     {
  363.     /* Set the delayed expunge flag and return. */
  364.     rambase->device.dd_Library.lib_Flags|=LIBF_DELEXP;
  365.     return 0;
  366.     }
  367.  
  368.     /* Kill device task and free all resources */
  369.     RemTask(rambase->port->mp_SigTask);
  370.     FreeMem(rambase->sigsem,sizeof(struct SignalSemaphore));
  371.     FreeMem(((struct Task *)rambase->port->mp_SigTask)->tc_SPLower,2048);
  372.     FreeMem(rambase->port->mp_SigTask,sizeof(struct Task));
  373.     FreeMem(rambase->port,sizeof(struct MsgPort));
  374.     CloseLibrary((struct Library *)rambase->utilitybase);
  375.     CloseLibrary((struct Library *)rambase->dosbase);
  376.  
  377.     /* Get rid of the device. Remove it from the list. */
  378.     Remove(&rambase->device.dd_Library.lib_Node);
  379.  
  380.     /* Get returncode here - FreeMem() will destroy the field. */
  381.     ret=rambase->seglist;
  382.  
  383.     /* Free the memory. */
  384.     FreeMem((char *)rambase-rambase->device.dd_Library.lib_NegSize,
  385.         rambase->device.dd_Library.lib_NegSize+rambase->device.dd_Library.lib_PosSize);
  386.  
  387.     return ret;
  388.     __AROS_FUNC_EXIT
  389. }
  390.  
  391. __AROS_LH0I(int, null, struct rambase *, rambase, 4, ramdev)
  392. {
  393.     __AROS_FUNC_INIT
  394.     return 0;
  395.     __AROS_FUNC_EXIT
  396. }
  397.  
  398. __AROS_LH1(void, beginio,
  399.  __AROS_LHA(struct IOFileSys *, iofs, A1),
  400.        struct rambase *, rambase, 5, ramdev)
  401. {
  402.     __AROS_FUNC_INIT
  403.  
  404.     /* WaitIO will look into this */
  405.     iofs->IOFS.io_Message.mn_Node.ln_Type=NT_MESSAGE;
  406.  
  407.     /* Nothing is done quick */
  408.     iofs->IOFS.io_Flags&=~IOF_QUICK;
  409.  
  410.     /* So let the device task do it */
  411.     PutMsg(rambase->port,&iofs->IOFS.io_Message);
  412.  
  413.     __AROS_FUNC_EXIT
  414. }
  415.  
  416. __AROS_LH1(LONG, abortio,
  417.  __AROS_LHA(struct IOFileSys *, iofs, A1),
  418.        struct rambase *, rambase, 6, ramdev)
  419. {
  420.     __AROS_FUNC_INIT
  421.     return 0;
  422.     __AROS_FUNC_EXIT
  423. }
  424.  
  425. static STRPTR Strdup(struct rambase *rambase, STRPTR string)
  426. {
  427.     STRPTR s2=string,s3;
  428.     while(*s2++)
  429.     ;
  430.     s3=(STRPTR)AllocMem(s2-string,MEMF_ANY);
  431.     if(s3!=NULL)
  432.     CopyMem(string,s3,s2-string);
  433.     return s3;
  434. }
  435.  
  436. static void Strfree(struct rambase *rambase, STRPTR string)
  437. {
  438.     STRPTR s2=string;
  439.     if(string==NULL)
  440.     return;
  441.     while(*s2++)
  442.     ;
  443.     FreeMem(string,s2-string);
  444. }
  445.  
  446. static LONG startup(struct rambase *rambase, STRPTR name, struct TagItem *args)
  447. {
  448.     struct filehandle *fhv, *fhc;
  449.     struct DosList *dlv, *dlc;
  450.     struct cnode *dev;
  451.     struct vnode *vol;
  452.  
  453.     /* Get compiler happy */
  454.     args=NULL;
  455.  
  456.     fhv=(struct filehandle*)AllocMem(sizeof(struct filehandle),MEMF_CLEAR);
  457.     if(fhv!=NULL)
  458.     {
  459.     vol=(struct vnode *)AllocMem(sizeof(struct vnode),MEMF_CLEAR);
  460.     if(vol!=NULL)
  461.     {
  462.         vol->name=Strdup(rambase,"Ram Disk");
  463.         if(vol->name!=NULL)
  464.         {
  465.         dlv=MakeDosEntry("Ram Disk",DLT_VOLUME);
  466.         if(dlv!=NULL)
  467.         {
  468.             fhc=(struct filehandle *)AllocMem(sizeof(struct filehandle),MEMF_CLEAR);
  469.             if(fhc!=NULL)
  470.             {
  471.             dev=(struct cnode *)AllocMem(sizeof(struct cnode),MEMF_CLEAR);
  472.             if(dev!=NULL)
  473.             {
  474.                 dev->name=Strdup(rambase,name);
  475.                 if(dev->name!=NULL)
  476.                 {
  477.                 dlc=MakeDosEntry(name,DLT_DEVICE);
  478.                 if(dlc!=NULL)
  479.                 {
  480.                     vol->type=ST_USERDIR;
  481.                     vol->protect=FMF_READ|FMF_WRITE;
  482.                     vol->self=vol;
  483.                     vol->doslist=dlv;
  484.                     NEWLIST((struct List *)&vol->list);
  485.                     fhv->node=(struct dnode *)vol;
  486.                     dlv->dol_Unit  =(struct Unit *)fhv;
  487.                     dlv->dol_Device=&rambase->device;
  488.                     dev->type=ST_LINKDIR;
  489.                     dev->self=dev;
  490.                     dev->volume=vol;
  491.                     dev->doslist=dlc;
  492.                     fhc->node=(struct dnode *)dev;
  493.                     dlc->dol_Unit  =(struct Unit *)fhc;
  494.                     dlc->dol_Device=&rambase->device;
  495.                     if(AddDosEntry(dlv))
  496.                     {
  497.                     if(AddDosEntry(dlc))
  498.                     {
  499.                         rambase->unitcount++;
  500.                         return 0;
  501.                     }
  502.                     RemDosEntry(dlv);
  503.                     }
  504.                     FreeDosEntry(dlc);
  505.                 }
  506.                 Strfree(rambase,dev->name);
  507.                 }
  508.                 FreeMem(dev,sizeof(struct cnode));
  509.             }
  510.             FreeMem(fhc,sizeof(struct filehandle));
  511.             }
  512.             FreeDosEntry(dlv);
  513.         }
  514.         Strfree(rambase,vol->name);
  515.         }
  516.         FreeMem(vol,sizeof(struct vnode));
  517.     }
  518.     FreeMem(fhv,sizeof(struct filehandle));
  519.     }
  520.     return ERROR_NO_FREE_STORE;
  521. }
  522.  
  523. static LONG getblock(struct rambase *rambase, struct fnode *file, LONG block, int mode, UBYTE **result)
  524. {
  525.     ULONG a, i;
  526.     UBYTE **p, **p2;
  527.  
  528.     if(block<0x10)
  529.     {
  530.     p=&file->blocks[block];
  531.     block=0;
  532.     i=0;
  533.     }else if(block<0x410)
  534.     {
  535.     block-=0x10;
  536.     p=(UBYTE **)&file->iblocks[block/0x100];
  537.     block&=0xff;
  538.     i=1;
  539.     }else if(block<0x10410)
  540.     {
  541.     block-=0x410;
  542.     p=(UBYTE **)&file->i2block;
  543.     i=2;
  544.     }else
  545.     {
  546.     block-=0x10410;
  547.     p=(UBYTE **)&file->i3block;
  548.     i=3;
  549.     }
  550.     switch(mode)
  551.     {
  552.     case -1:
  553.         p2=(UBYTE **)*p;
  554.         if(!block)
  555.         *p=NULL;
  556.         p=p2;
  557.         while(i--&&p!=NULL)
  558.         {
  559.         a=(block>>i*8)&0xff;
  560.         p2=(UBYTE **)p[a];
  561.         if(!(block&((1<<i*8)-1)))
  562.         {
  563.             p[a]=NULL;
  564.             if(!a)
  565.             FreeMem(p,PBLOCKSIZE);
  566.         }
  567.         p=p2;
  568.         }
  569.         if(p!=NULL)
  570.         FreeMem(p,BLOCKSIZE);
  571.         break;
  572.     case 0:
  573.         p=(UBYTE **)*p;
  574.         while(i--&&p!=NULL)
  575.         p=((UBYTE ***)p)[(block>>i*8)&0xff];
  576.         *result=(UBYTE *)p;
  577.         break;
  578.     case 1:
  579.         while(i--)
  580.         {
  581.         if(*p==NULL)
  582.         {
  583.             *p=AllocMem(PBLOCKSIZE,MEMF_CLEAR);
  584.             if(*p==NULL)
  585.             return ERROR_NO_FREE_STORE;
  586.         }
  587.         p=(UBYTE **)*p+((block>>i*8)&0xff);
  588.         }
  589.         if(*p==NULL)
  590.         {
  591.         *p=AllocMem(BLOCKSIZE,MEMF_CLEAR);
  592.         if(*p==NULL)
  593.             return ERROR_NO_FREE_STORE;
  594.         }
  595.         *result=*p;
  596.         break;
  597.     }
  598.     return 0;
  599. }
  600.  
  601. static void zerofill(UBYTE *address, ULONG size)
  602. {
  603.     while(size--)
  604.     *address++=0;
  605. }
  606.  
  607. static void shrinkfile(struct rambase *rambase, struct fnode *file, LONG size)
  608. {
  609.     ULONG blocks, block;
  610.     UBYTE *p;
  611.  
  612.     blocks=(size+BLOCKSIZE-1)/BLOCKSIZE;
  613.     block =(file->size+BLOCKSIZE-1)/BLOCKSIZE;
  614.     for(;block-->blocks;)
  615.     (void)getblock(rambase,file,block,-1,&p);
  616.     if(size&0xff)
  617.     {
  618.     (void)getblock(rambase,file,size,0,&p);
  619.     if(p!=NULL)
  620.         zerofill(p+(size&0xff),-size&0xff);
  621.     }
  622.     file->size=size;
  623. }
  624.  
  625. static void delete(struct rambase *rambase, struct fnode *file)
  626. {
  627.     struct hnode *link, *new, *more;
  628.     struct Node *node;
  629.  
  630.     Strfree(rambase,file->name);
  631.     Strfree(rambase,file->comment);
  632.     Remove((struct Node *)file);
  633.  
  634.     if(file->type==ST_LINKDIR)
  635.     {
  636.     /* It is a link. Remove it from the chain. */
  637.     link=((struct hnode *)file)->orig;
  638.     ((struct hnode *)file)->orig=NULL;
  639.     file->type=link->type;
  640.     while((struct fnode *)link->link!=file)
  641.         link=link->link;
  642.     link->link=file->link;
  643.     }else if(file->link!=NULL)
  644.     {
  645.     /* If there is a hard link to the object make the link the original */
  646.     link=file->link;
  647.     link->type=file->type;
  648.     more=new->link;
  649.     while(more!=NULL)
  650.     {
  651.         more->orig=new;
  652.         more=more->link;
  653.     }
  654.     switch(file->type)
  655.     {
  656.         case ST_USERDIR:
  657.         while((node=RemHead((struct List *)&((struct dnode *)file)->list))!=NULL)
  658.             AddTail((struct List *)&((struct dnode *)file)->list,node);
  659.         break;
  660.         case ST_FILE:
  661.         CopyMemQuick(&file->size,&((struct fnode *)new)->size,sizeof(struct fnode)-offsetof(struct fnode,size));
  662.         zerofill((UBYTE *)&file->size,sizeof(struct fnode)-offsetof(struct fnode,size));
  663.         break;
  664.         case ST_SOFTLINK:
  665.         ((struct snode *)new)->contents=((struct snode *)file)->contents;
  666.         ((struct snode *)file)->contents=NULL;
  667.         break;
  668.     }
  669.     }
  670.     switch(file->type)
  671.     {
  672.     case ST_USERDIR:
  673.         FreeMem(file,sizeof(struct dnode));
  674.         return;
  675.     case ST_FILE:
  676.         shrinkfile(rambase,file,0);
  677.         FreeMem(file,sizeof(struct fnode));
  678.         return;
  679.     case ST_SOFTLINK:
  680.         Strfree(rambase,((struct snode *)file)->contents);
  681.         FreeMem(file,sizeof(struct snode));
  682.         return;
  683.     }
  684. }
  685.  
  686. static int fstrcmp(struct rambase *rambase, char *s1, char *s2)
  687. {
  688.     for(;;)
  689.     {
  690.     if(ToLower(*s1)!=ToLower(*s2))
  691.         return *s1||*s2!='/';
  692.     if(!*s1)
  693.         return 0;
  694.     s1++; s2++;
  695.     }
  696. }
  697.  
  698. static LONG findname(struct rambase *rambase, STRPTR *name, struct dnode **dnode)
  699. {
  700.     struct dnode *cur=*dnode;
  701.     char *rest=*name;
  702.  
  703.     for(;;)
  704.     {
  705.     if(cur->type==ST_LINKDIR)
  706.         cur=(struct dnode *)((struct hnode *)cur)->orig;
  707.     if(!*rest)
  708.         break;
  709.     if(*rest=='/')
  710.     {
  711.         if((struct dnode *)cur->volume==cur)
  712.         return ERROR_OBJECT_NOT_FOUND;
  713.         while(cur->node.mln_Pred!=NULL)
  714.         cur=(struct dnode *)cur->node.mln_Pred;
  715.         cur=(struct dnode *)((BYTE *)cur-offsetof(struct dnode,list));
  716.     }else
  717.     {
  718.         if(cur->type==ST_SOFTLINK)
  719.         {
  720.         *dnode=cur;
  721.         *name=rest;
  722.         return ERROR_IS_SOFT_LINK;
  723.         }
  724.         if(cur->type!=ST_USERDIR)
  725.         return ERROR_DIR_NOT_FOUND;
  726.         *dnode=cur;
  727.         cur=(struct dnode *)cur->list.mlh_Head;
  728.         for(;;)
  729.         {
  730.         if(cur->node.mln_Succ==NULL)
  731.         {
  732.             *name=rest;
  733.             return ERROR_OBJECT_NOT_FOUND;
  734.         }
  735.         if(!fstrcmp(rambase,cur->name,rest))
  736.             break;
  737.         cur=(struct dnode *)cur->node.mln_Succ;
  738.         }
  739.     }
  740.     while(*rest)
  741.         if(*rest++=='/')
  742.             break;
  743.     }
  744.     *dnode=cur;
  745.     return 0;
  746. }
  747.  
  748. static LONG set_file_size(struct rambase *rambase, struct filehandle *handle, LONG *offl, LONG *offh, LONG mode)
  749. {
  750.     struct fnode *file=(struct fnode *)handle->node;
  751.     LONG size=*offl;
  752.  
  753.     if((size<0?-1:0)!=*offh)
  754.     return ERROR_SEEK_ERROR;
  755.  
  756.     if((size<0?-1:0)!=*offh)
  757.     return ERROR_SEEK_ERROR;
  758.  
  759.     if(file->type!=ST_FILE)
  760.     return ERROR_OBJECT_WRONG_TYPE;
  761.     switch(mode)
  762.     {
  763.     case OFFSET_BEGINNING:    break;
  764.     case OFFSET_CURRENT:    size+=handle->position; break;
  765.     case OFFSET_END:    size+=file->size; break;
  766.     default:        return ERROR_NOT_IMPLEMENTED;
  767.     }
  768.     if(size<0)
  769.     return ERROR_SEEK_ERROR;
  770.     if(size<file->size)
  771.     shrinkfile(rambase,file,size);
  772.     file->size=*offl=size;
  773.     *offh=0;
  774.     return 0;
  775. }
  776.  
  777. static LONG read(struct rambase *rambase, struct filehandle *handle, APTR buffer, LONG *numbytes)
  778. {
  779.     struct fnode *file=(struct fnode *)handle->node;
  780.     ULONG num =*numbytes;
  781.     ULONG size=file->size;
  782.     ULONG block, offset;
  783.     UBYTE *buf=buffer, *p;
  784.  
  785.     if(handle->position>=size)
  786.     num=0;
  787.     else if(handle->position+num>size)
  788.     num=size-handle->position;
  789.     block =handle->position/BLOCKSIZE;
  790.     offset=handle->position&(BLOCKSIZE-1);
  791.     size  =BLOCKSIZE-offset;
  792.     while(num)
  793.     {
  794.     if(size>num)
  795.         size=num;
  796.     (void)getblock(rambase,file,block,0,&p);
  797.     if(p!=NULL)
  798.         CopyMem(p+offset,buffer,size);
  799.     else
  800.         zerofill(buffer,size);
  801.     buffer+=size;
  802.     num   -=size;
  803.     block++;
  804.     offset=0;
  805.     size=BLOCKSIZE;
  806.     }
  807.     *numbytes=(UBYTE *)buffer-buf;
  808.     handle->position+=*numbytes;
  809.     return 0;
  810. }
  811.  
  812. static LONG write(struct rambase *rambase, struct filehandle *handle, UBYTE *buffer, LONG *numbytes)
  813. {
  814.     struct fnode *file=(struct fnode *)handle->node;
  815.     ULONG num =*numbytes;
  816.     ULONG size=file->size;
  817.     ULONG block, offset;
  818.     UBYTE *buf=buffer, *p;
  819.     LONG error=0;
  820.  
  821.     if((LONG)(handle->position+num)<0)
  822.     return ERROR_OBJECT_TOO_LARGE;
  823.     block =handle->position/BLOCKSIZE;
  824.     offset=handle->position&(BLOCKSIZE-1);
  825.     size  =BLOCKSIZE-offset;
  826.     while(num)
  827.     {
  828.     if(size>num)
  829.         size=num;
  830.     error=getblock(rambase,file,block,1,&p);
  831.     if(error)
  832.         break;
  833.     CopyMem(buffer,p+offset,size);
  834.     buffer+=size;
  835.     num   -=size;
  836.     block++;
  837.     offset=0;
  838.     size=BLOCKSIZE;
  839.     }
  840.     *numbytes=(UBYTE *)buffer-buf;
  841.     handle->position+=*numbytes;
  842.     if(handle->position>file->size)
  843.     file->size=handle->position;
  844.     return error;
  845. }
  846.  
  847. static LONG lock(struct dnode *dir, ULONG mode)
  848. {
  849.     if((mode&FMF_EXECUTE)&&!(dir->protect&FMF_EXECUTE))
  850.     return ERROR_NOT_EXECUTABLE;
  851.     if((mode&FMF_WRITE)&&!(dir->protect&FMF_WRITE))
  852.     return ERROR_WRITE_PROTECTED;
  853.     if((mode&FMF_READ)&&!(dir->protect&FMF_READ))
  854.     return ERROR_READ_PROTECTED;
  855.     if(mode&FMF_LOCK)
  856.     {
  857.     if(dir->usecount)
  858.         return ERROR_OBJECT_IN_USE;
  859.     dir->usecount=~0ul/2+1;
  860.     }else
  861.     if(dir->usecount<0)
  862.         return ERROR_OBJECT_IN_USE;
  863.     dir->usecount++;
  864.     dir->volume->volcount++;
  865.     return 0;
  866. }
  867.  
  868. static LONG open_(struct rambase *rambase, struct filehandle **handle, STRPTR name, ULONG mode)
  869. {
  870.     struct dnode *dir=(*handle)->node;
  871.     struct filehandle *fh;
  872.     LONG error;
  873.  
  874.     fh=(struct filehandle *)AllocMem(sizeof(struct filehandle),MEMF_CLEAR);
  875.     if(fh!=NULL)
  876.     {
  877.     error=findname(rambase,&name,&dir);
  878.     if(!error)
  879.     {
  880.         error=lock(dir,mode);
  881.         if(!error)
  882.         {
  883.         fh->node=dir;
  884.         *handle=fh;
  885.         return 0;
  886.         }
  887.     }
  888.     FreeMem(fh,sizeof(struct filehandle));
  889.     }else
  890.     error=ERROR_NO_FREE_STORE;
  891.     return error;
  892. }
  893.  
  894. static LONG open_file(struct rambase *rambase, struct filehandle **handle, STRPTR name, ULONG mode, ULONG protect)
  895. {
  896.     struct dnode *dir=(*handle)->node;
  897.     struct filehandle *fh;
  898.     LONG error;
  899.  
  900.     fh=AllocMem(sizeof(struct filehandle),MEMF_CLEAR);
  901.     if(fh!=NULL)
  902.     {
  903.     error=findname(rambase,&name,&dir);
  904.     if((mode&FMF_CREATE)&&error==ERROR_OBJECT_NOT_FOUND)
  905.     {
  906.         char *s=name;
  907.         struct fnode *file;
  908.         while(*s)
  909.         if(*s++=='/')
  910.             return error;
  911.         file=(struct fnode *)AllocMem(sizeof(struct fnode),MEMF_CLEAR);
  912.         if(file!=NULL)
  913.         {
  914.         file->name=Strdup(rambase,name);
  915.         if(file->name!=NULL)
  916.         {
  917.             file->type=ST_FILE;
  918.             file->protect=protect;
  919.             file->volume=dir->volume;
  920.             AddTail((struct List *)&dir->list,(struct Node *)file);
  921.             error=lock((struct dnode *)file,mode);
  922.             if(!error)
  923.             {
  924.             fh->node=dir;
  925.             *handle=fh;
  926.             return 0;
  927.             }
  928.             Strfree(rambase,file->name);
  929.         }
  930.         FreeMem(file,sizeof(struct fnode));
  931.         }
  932.         error=ERROR_NO_FREE_STORE;
  933.     }else if(!error)
  934.     {
  935.         if(dir->type!=ST_FILE)
  936.         error=ERROR_OBJECT_WRONG_TYPE;
  937.         else
  938.         {
  939.         error=lock(dir,mode);
  940.         if(!error)
  941.         {
  942.             fh->node=dir;
  943.             *handle=fh;
  944.             return 0;
  945.         }
  946.         }
  947.     }
  948.     FreeMem(fh,sizeof(struct filehandle));
  949.     }
  950.     return error;
  951. }
  952.  
  953. static LONG create_dir(struct rambase *rambase, struct filehandle **handle, STRPTR name, ULONG protect)
  954. {
  955.     struct dnode *dir=(*handle)->node, *new;
  956.     struct filehandle *fh;
  957.     STRPTR s;
  958.     LONG error;
  959.  
  960.     error=findname(rambase,&name,&dir);
  961.     if(!error)
  962.     return ERROR_OBJECT_EXISTS;
  963.     if(error!=ERROR_OBJECT_NOT_FOUND)
  964.     return error;
  965.     s=name;
  966.     while(*s)
  967.     if(*s++=='/')
  968.         return error;
  969.     fh=AllocMem(sizeof(struct filehandle),MEMF_CLEAR);
  970.     if(fh!=NULL)
  971.     {
  972.     new=(struct dnode *)AllocMem(sizeof(struct dnode),MEMF_CLEAR);
  973.     if(new!=NULL)
  974.     {
  975.         new->name=Strdup(rambase,name);
  976.         if(new->name!=NULL)
  977.         {
  978.         new->type=ST_USERDIR;
  979.         new->protect=protect;
  980.         new->volume=dir->volume;
  981.         new->volume->volcount++;
  982.         new->usecount=~0ul/2+2;
  983.         NEWLIST((struct List *)&new->list);
  984.         AddTail((struct List *)&dir->list,(struct Node *)new);
  985.         fh->node=new;
  986.         *handle=fh;
  987.         return 0;
  988.         }
  989.         FreeMem(new,sizeof(struct dnode));
  990.     }
  991.     FreeMem(fh,sizeof(struct filehandle));
  992.     }
  993.     return ERROR_NO_FREE_STORE;
  994. }
  995.  
  996. static LONG free_lock(struct rambase *rambase, struct filehandle *filehandle)
  997. {
  998.     struct dnode *dnode=filehandle->node;
  999.     dnode->usecount=(dnode->usecount-1)&~0ul/2;
  1000.     FreeMem(filehandle,sizeof(struct filehandle));
  1001.     dnode->volume->volcount--;
  1002.     return 0;
  1003. }
  1004.  
  1005. static LONG seek(struct rambase *rambase, struct filehandle *filehandle, LONG *posh, LONG *posl, LONG mode)
  1006. {
  1007.     struct fnode *file=(struct fnode *)filehandle->node;
  1008.     LONG pos=*posl;
  1009.  
  1010.     if((pos<0?-1:0)!=*posh)
  1011.     return ERROR_SEEK_ERROR;
  1012.     if(file->type!=ST_FILE)
  1013.     return ERROR_OBJECT_WRONG_TYPE;
  1014.     switch(mode)
  1015.     {
  1016.     case OFFSET_BEGINNING:    break;
  1017.     case OFFSET_CURRENT:    pos+=filehandle->position; break;
  1018.     case OFFSET_END:    pos+=file->size; break;
  1019.     default:        return ERROR_NOT_IMPLEMENTED;
  1020.     }
  1021.     if(pos<0)
  1022.     return ERROR_SEEK_ERROR;
  1023.     *posh=0;
  1024.     *posl=filehandle->position;
  1025.     filehandle->position=pos;
  1026.     return 0;
  1027. }
  1028.  
  1029. static const ULONG sizes[]=
  1030. { 0, offsetof(struct ExAllData,ed_Type), offsetof(struct ExAllData,ed_Size),
  1031.   offsetof(struct ExAllData,ed_Prot), offsetof(struct ExAllData,ed_Days),
  1032.   offsetof(struct ExAllData,ed_Comment), offsetof(struct ExAllData,ed_OwnerUID),
  1033.   sizeof(struct ExAllData)
  1034. };
  1035.  
  1036. static LONG examine(struct fnode *file, struct ExAllData *ead, ULONG size, ULONG type)
  1037. {
  1038.     STRPTR next, end, name;
  1039.     if(type>ED_OWNER)
  1040.     return ERROR_BAD_NUMBER;
  1041.     next=(STRPTR)ead+sizes[type];
  1042.     end=(STRPTR)ead+size;
  1043.     switch(type)
  1044.     {
  1045.     case ED_OWNER:
  1046.         ead->ed_OwnerUID=0;
  1047.         ead->ed_OwnerGID=0;
  1048.     case ED_COMMENT:
  1049.         if(file->comment!=NULL)
  1050.         {
  1051.         ead->ed_Comment=next;
  1052.         name=file->comment;
  1053.         for(;;)
  1054.         {
  1055.             if(next>=end)
  1056.             return ERROR_BUFFER_OVERFLOW;
  1057.             if(!(*next++=*name++))
  1058.             break;
  1059.         }
  1060.         }else
  1061.         ead->ed_Comment=NULL;
  1062.     case ED_DATE:
  1063.         ead->ed_Days=0;
  1064.         ead->ed_Mins=0;
  1065.         ead->ed_Ticks=0;
  1066.     case ED_PROTECTION:
  1067.         ead->ed_Prot=file->protect;
  1068.     case ED_SIZE:
  1069.         ead->ed_Size=file->size;
  1070.     case ED_TYPE:
  1071.         ead->ed_Type=file->type;
  1072.         if(((struct vnode *)file)->self==(struct vnode *)file)
  1073.         ead->ed_Type=ST_ROOT;
  1074.     case ED_NAME:
  1075.         ead->ed_Name=next;
  1076.         name=file->name;
  1077.         for(;;)
  1078.         {
  1079.         if(next>=end)
  1080.             return ERROR_BUFFER_OVERFLOW;
  1081.         if(!(*next++=*name++))
  1082.             break;
  1083.         }
  1084.     case 0:
  1085.         ead->ed_Next=(struct ExAllData *)(((IPTR)next+PTRALIGN-1)&~(PTRALIGN-1));
  1086.     }
  1087.     return 0;
  1088. }
  1089.  
  1090. static LONG examine_all(struct filehandle *dir, struct ExAllData *ead, ULONG size, ULONG type)
  1091. {
  1092.     STRPTR end;
  1093.     struct ExAllData *last=NULL;
  1094.     struct fnode *ent;
  1095.     LONG error;
  1096.     end=(STRPTR)ead+size;
  1097.     if(dir->node->type!=ST_USERDIR)
  1098.     return ERROR_OBJECT_WRONG_TYPE;
  1099.     ent=(struct fnode *)dir->position;
  1100.     if(ent==NULL)
  1101.     {
  1102.     ent=(struct fnode *)dir->node->list.mlh_Head;
  1103.     ent->usecount++;
  1104.     }
  1105.     if(ent->node.mln_Succ==NULL)
  1106.     return ERROR_NO_MORE_ENTRIES;
  1107.     ent->usecount--;
  1108.     do
  1109.     {
  1110.     error=examine(ent,ead,end-(STRPTR)ead,type);
  1111.     if(error==ERROR_BUFFER_OVERFLOW)
  1112.     {
  1113.         if(last==NULL)
  1114.         return error;
  1115.         ent->usecount++;
  1116.         last->ed_Next=NULL;
  1117.         dir->position=(IPTR)ent;
  1118.         return 0;
  1119.     }
  1120.     last=ead;
  1121.     ead=ead->ed_Next;
  1122.     ent=(struct fnode *)ent->node.mln_Succ;
  1123.     }while(ent->node.mln_Succ!=NULL);
  1124.     last->ed_Next=NULL;
  1125.     dir->position=(IPTR)ent;
  1126.     return 0;
  1127. }
  1128.  
  1129. static LONG delete_object(struct rambase *rambase, struct filehandle *filehandle, STRPTR name)
  1130. {
  1131.     struct dnode *file=filehandle->node;
  1132.     LONG error;
  1133.     error=findname(rambase,&name,&file);
  1134.     if(error)
  1135.     return error;
  1136.     if((struct dnode *)file->volume==file)
  1137.     return ERROR_OBJECT_WRONG_TYPE;
  1138.     if(file->usecount)
  1139.     return ERROR_OBJECT_IN_USE;
  1140.     if(!(file->protect&FIBF_DELETE))
  1141.     return ERROR_DELETE_PROTECTED;
  1142.     if(file->type==ST_USERDIR&&file->list.mlh_Head->mln_Succ!=NULL)
  1143.     return ERROR_DIRECTORY_NOT_EMPTY;
  1144.     delete(rambase,(struct fnode *)file);
  1145.     return 0;
  1146. }
  1147.  
  1148. LONG die(struct rambase *rambase, struct filehandle *handle)
  1149. {
  1150.     struct cnode *dev;
  1151.     struct vnode *vol;
  1152.     struct dnode *dir;
  1153.     struct fnode *file;
  1154.  
  1155.     dev=(struct cnode *)handle->node;
  1156.     free_lock(rambase,handle);
  1157.     if(dev->type!=ST_LINKDIR||dev->self!=dev)
  1158.     return ERROR_OBJECT_WRONG_TYPE;
  1159.     vol=dev->volume;
  1160.     if(vol->volcount)
  1161.     return ERROR_OBJECT_IN_USE;
  1162.  
  1163.     RemDosEntry(vol->doslist);
  1164.     FreeDosEntry(vol->doslist);
  1165.     RemDosEntry(dev->doslist);
  1166.     FreeDosEntry(dev->doslist);
  1167.  
  1168.     while(vol->list.mlh_Head->mln_Succ!=NULL)
  1169.     {
  1170.     dir=(struct dnode *)vol->list.mlh_Head;
  1171.     if(dir->type==ST_USERDIR)
  1172.         while((file=(struct fnode *)RemHead((struct List *)&dir->list))!=NULL)
  1173.         AddTail((struct List *)&vol->list,(struct Node *)dir);
  1174.     delete(rambase,(struct fnode *)dir);
  1175.     }
  1176.     Strfree(rambase,vol->name);
  1177.     FreeMem(vol,sizeof(struct vnode));
  1178.  
  1179.     Strfree(rambase,dev->name);
  1180.     FreeMem(dev,sizeof(struct cnode));
  1181.     rambase->unitcount--;
  1182.     return 0;
  1183. }
  1184.  
  1185. void deventry(struct rambase *rambase)
  1186. {
  1187.     struct IOFileSys *iofs;
  1188.     struct dnode *dir;
  1189.     LONG error=0;
  1190.     /*
  1191.     Init device port. AllocSignal() cannot fail because this is a
  1192.     freshly created task with all signal bits still free.
  1193.     */
  1194.     rambase->port->mp_SigBit=AllocSignal(-1);
  1195.     rambase->port->mp_Flags=PA_SIGNAL;
  1196.  
  1197.     /* Get and process the messages. */
  1198.     for(;;)
  1199.     {
  1200.     while((iofs=(struct IOFileSys *)GetMsg(rambase->port))!=NULL)
  1201.     {
  1202.         switch(iofs->IOFS.io_Command)
  1203.         {
  1204.         case FSA_MOUNT:
  1205.             /*
  1206.             mount a new dos device (a new filesystem)
  1207.             Unit *root;    root handle on return
  1208.             STRPTR name;   device name without colon
  1209.             ULONG *args;   further arguments
  1210.             */
  1211.             AddTail((struct List *)&rambase->waitdoslist,&iofs->IOFS.io_Message.mn_Node);
  1212.             continue;
  1213.  
  1214.         case FSA_DISMOUNT:
  1215.             /*
  1216.             Free the lock then try to dismount dos device
  1217.             Unit *root;    handle to device's root directory
  1218.             */
  1219.             AddTail((struct List *)&rambase->waitdoslist,&iofs->IOFS.io_Message.mn_Node);
  1220.             continue;
  1221.  
  1222.         case FSA_OPEN:
  1223.             /*
  1224.             get handle on a file or directory
  1225.             Unit *current; current directory / new handle on return
  1226.             STRPTR name;   file- or directoryname
  1227.             LONG mode;     open mode
  1228.             */
  1229.             error=open_(rambase,(struct filehandle **)&iofs->IOFS.io_Unit,
  1230.                       (STRPTR)iofs->io_Args[0], iofs->io_Args[1]);
  1231.             break;
  1232.  
  1233.         case FSA_OPEN_FILE:
  1234.             /*
  1235.             open a file or create a new one
  1236.             Unit *current; current directory / new handle on return
  1237.             STRPTR name;   file- or directoryname
  1238.             LONG mode;     open mode
  1239.             LONG protect;  protection flags if a new file is created
  1240.             */
  1241.             error=open_file(rambase,(struct filehandle **)&iofs->IOFS.io_Unit,
  1242.                       (STRPTR)iofs->io_Args[0], iofs->io_Args[1],
  1243.                       iofs->io_Args[2]);
  1244.             break;
  1245.  
  1246.         case FSA_READ:
  1247.             /*
  1248.             read a number of bytes from a file
  1249.             Unit *current; filehandle
  1250.             APTR buffer;   data
  1251.             LONG numbytes; number of bytes to read /
  1252.                        number of bytes read on return,
  1253.                        0 if there are no more bytes in the file
  1254.             */
  1255.             error=read(rambase,(struct filehandle *)iofs->IOFS.io_Unit,
  1256.                  (APTR)iofs->io_Args[0], &iofs->io_Args[1]);
  1257.             break;
  1258.  
  1259.         case FSA_WRITE:
  1260.             /*
  1261.             write a number of bytes to a file
  1262.             Unit *current; filehandle
  1263.             APTR buffer;   data
  1264.             LONG numbytes; number of bytes to write /
  1265.                        number of bytes written on return
  1266.             */
  1267.             error=write(rambase,(struct filehandle *)iofs->IOFS.io_Unit,
  1268.                   (APTR)iofs->io_Args[0], &iofs->io_Args[1]);
  1269.             break;
  1270.  
  1271.         case FSA_SEEK:
  1272.             /*
  1273.             set / read position in file
  1274.             Unit *current; filehandle
  1275.             LONG posh;
  1276.             LONG posl;     relative position /
  1277.                        old position on return
  1278.             LONG mode;     one of OFFSET_BEGINNING, OFFSET_CURRENT,
  1279.                        OFFSET_END
  1280.             */
  1281.             error=seek(rambase,(struct filehandle *)iofs->IOFS.io_Unit,
  1282.                  &iofs->io_Args[0], &iofs->io_Args[1], iofs->io_Args[2]);
  1283.             break;
  1284.  
  1285.         case FSA_CLOSE:
  1286.             /*
  1287.             get rid of a handle
  1288.             Unit *current; filehandle
  1289.             */
  1290.             error=free_lock(rambase,(struct filehandle *)iofs->IOFS.io_Unit);
  1291.             break;
  1292.  
  1293.         case FSA_EXAMINE:
  1294.             /*
  1295.             Get information about the current object
  1296.             Unit *current; current object
  1297.             struct ExAllData *ead; buffer to be filled
  1298.             ULONG size;    size of the buffer
  1299.             ULONG type;    type of information to get
  1300.             */
  1301.             error=examine((struct fnode *)((struct filehandle *)iofs->IOFS.io_Unit)->node,
  1302.                   (struct ExAllData*)iofs->io_Args[0],
  1303.                   iofs->io_Args[1], iofs->io_Args[2]);
  1304.             break;
  1305.  
  1306.         case FSA_EXAMINE_ALL:
  1307.             /*
  1308.             Read the current directory
  1309.             Unit *current; current directory
  1310.             struct ExAllData *ead; buffer to be filled
  1311.             ULONG size;    size of the buffer
  1312.             ULONG type;    type of information to get
  1313.             */
  1314.             error=examine_all((struct filehandle *)iofs->IOFS.io_Unit,
  1315.                       (struct ExAllData*)iofs->io_Args[0],
  1316.                       iofs->io_Args[1], iofs->io_Args[2]);
  1317.             break;
  1318.  
  1319.         case FSA_CREATE_DIR:
  1320.             /*
  1321.             Build lock and open a new directory
  1322.             Unit *current; current directory
  1323.             STRPTR name;   name of the dir to create
  1324.             LONG protect;  Protection flags for the new dir
  1325.             */
  1326.             error=create_dir(rambase,(struct filehandle **)&iofs->IOFS.io_Unit,
  1327.                      (STRPTR)iofs->io_Args[0], iofs->io_Args[1]);
  1328.             break;
  1329.  
  1330.         case FSA_DELETE_OBJECT:
  1331.             /*
  1332.             Delete file or directory
  1333.             Unit *current; current directory
  1334.             STRPTR name;   filename
  1335.             */
  1336.             error=delete_object(rambase,(struct filehandle *)iofs->IOFS.io_Unit,
  1337.                     (STRPTR)iofs->io_Args[0]);
  1338.             break;
  1339.  
  1340.         case FSA_SET_PROTECT:
  1341.             /*
  1342.             Set protection bits for a certain file or directory.
  1343.             Unit *current; current directory
  1344.             STRPTR name;   filename
  1345.             ULONG protect; new protection bits
  1346.             */
  1347.             dir=((struct filehandle *)iofs->IOFS.io_Unit)->node;
  1348.             error=findname(rambase,(STRPTR *)&iofs->io_Args[0],&dir);
  1349.             if(!error)
  1350.             dir->protect=iofs->io_Args[1];
  1351.             break;
  1352.  
  1353.         case FSA_SET_OWNER:
  1354.             /*
  1355.             Set owner and group of the file or directory
  1356.             Unit *current; current directory
  1357.             STRPTR name;   filename
  1358.             ULONG UID;
  1359.             ULONG GID;
  1360.             */
  1361.             dir=((struct filehandle *)iofs->IOFS.io_Unit)->node;
  1362.             error=findname(rambase,(STRPTR *)&iofs->io_Args[0],&dir);
  1363.             if(!error)
  1364.             {
  1365.             }
  1366.             break;
  1367.  
  1368.         case FSA_SET_DATE:
  1369.             /*
  1370.             Set creation date of the file
  1371.             Unit *current; current directory
  1372.             STRPTR name;   filename
  1373.             ULONG days;
  1374.             ULONG mins;
  1375.             ULONG ticks;   timestamp
  1376.             */
  1377.             dir=((struct filehandle *)iofs->IOFS.io_Unit)->node;
  1378.             error=findname(rambase,(STRPTR *)&iofs->io_Args[0],&dir);
  1379.             if(!error)
  1380.             {
  1381.             }
  1382.             break;
  1383.  
  1384.         case FSA_SET_COMMENT:
  1385.             /*
  1386.             Set a comment for the file or directory;
  1387.             Unit *current; current directory
  1388.             STRPTR name;   filename
  1389.             STRPTR comment; NUL terminated C string or NULL.
  1390.             */
  1391.             dir=((struct filehandle *)iofs->IOFS.io_Unit)->node;
  1392.             error=findname(rambase,(STRPTR *)&iofs->io_Args[0],&dir);
  1393.             if(!error)
  1394.             {
  1395.             if(iofs->io_Args[1])
  1396.             {
  1397.                 STRPTR s=Strdup(rambase,(STRPTR)iofs->io_Args[0]);
  1398.                 if(s!=NULL)
  1399.                 {
  1400.                 Strfree(rambase,dir->comment);
  1401.                 dir->comment=s;
  1402.                 }else
  1403.                 error=ERROR_NO_FREE_STORE;
  1404.             }else
  1405.             {
  1406.                 Strfree(rambase,dir->comment);
  1407.                 dir->comment=NULL;
  1408.             }
  1409.             }
  1410.             break;
  1411.  
  1412.         case FSA_SET_FILE_SIZE:
  1413.             /*
  1414.             Set a new size for the file.
  1415.             Unit *file;    filehandle
  1416.             LONG offh;
  1417.             LONG offl;     offset to current position/
  1418.                        new size on return
  1419.             LONG mode;     relative to what (see Seek)
  1420.             */
  1421.             error=set_file_size(rambase,(struct filehandle *)iofs->IOFS.io_Unit,
  1422.                     &iofs->io_Args[0],&iofs->io_Args[1],iofs->io_Args[2]);
  1423.             break;
  1424.  
  1425.         default:
  1426.             error=ERROR_NOT_IMPLEMENTED;
  1427.             break;
  1428. /*
  1429.   FSA_FILE_MODE
  1430.     Change or read the mode of a single filehandle
  1431.     Unit *current; filehandle to change
  1432.     ULONG newmode; new mode/old mode on return
  1433.     ULONG mask;    bits affected
  1434.  
  1435.   FSA_MOUNT_MODE
  1436.     Change or read the mode of the filesystem
  1437.     Unit *current; filesystem to change
  1438.     ULONG newmode; new mode/old mode on return
  1439.     ULONG mask;    bits affected
  1440.     STRPTR passwd; password for MMF_LOCKED
  1441.  
  1442.   FSA_MAKE_HARDLINK
  1443.     Create a hard link on a file, directory or soft link
  1444.     Unit *current; current directory
  1445.     STRPTR name;   softlink name
  1446.     Unit *target;  target handle
  1447.  
  1448.   FSA_MAKE_SOFTLINK
  1449.     Create a soft link to another object
  1450.     Unit *current; current directory
  1451.     STRPTR name;   softlink name
  1452.     STRPTR target; target name
  1453.  
  1454.   FSA_RENAME
  1455.   FSA_READ_LINK
  1456.   FSA_DISK_INFO
  1457.   FSA_SERIALIZE_DISK
  1458.   FSA_WAIT_CHAR
  1459.   FSA_INFO
  1460.   FSA_TIMER
  1461.   FSA_DISK_TYPE
  1462.   FSA_DISK_CHANGE
  1463.   FSA_SAME_LOCK
  1464.   FSA_CHANGE_SIGNAL
  1465.   FSA_FORMAT
  1466.   FSA_IS_FILESYSTEM
  1467.   FSA_EXAMINE_ALL
  1468.   FSA_EXAMINE_FH
  1469.   FSA_ADD_NOTIFY
  1470.   FSA_REMOVE_NOTIFY
  1471.   FSA_EXAMINE_ALL_END
  1472.  
  1473. */
  1474.         }
  1475.         iofs->io_DosError=error;
  1476.         ReplyMsg(&iofs->IOFS.io_Message);
  1477.     }
  1478.     if(rambase->waitdoslist.mlh_Head->mln_Succ!=NULL)
  1479.     {
  1480.         if(!AttemptLockDosList(LDF_DEVICES|LDF_VOLUMES|LDF_WRITE))
  1481.         Delay(TICKS_PER_SECOND/2);
  1482.         else
  1483.         {
  1484.         while((iofs=(struct IOFileSys *)RemHead((struct List *)&rambase->waitdoslist))!=NULL)
  1485.         {
  1486.             if(iofs->IOFS.io_Command==FSA_MOUNT)
  1487.             error=startup(rambase,(STRPTR)iofs->io_Args[0],
  1488.                       (struct TagItem *)iofs->io_Args[1]);
  1489.             else
  1490.             error=die(rambase,(struct filehandle *)iofs->IOFS.io_Unit);
  1491.             iofs->io_DosError=error;
  1492.             ReplyMsg(&iofs->IOFS.io_Message);
  1493.         }
  1494.         UnLockDosList(LDF_DEVICES|LDF_VOLUMES|LDF_WRITE);
  1495.         }
  1496.     }
  1497. #if 0
  1498.     if(rambase->iofs!=NULL)
  1499.     {
  1500.         iofs=rambase->iofs;
  1501.         if(iofs->IOFS.io_Message.mn_Node.ln_Type==NT_MESSAGE)
  1502.         {
  1503.         abort_notify(rambase,iofs);
  1504.         iofs->io_DosError=ERROR_BREAK;
  1505.         rambase->iofs=NULL;
  1506.         ReplyMsg(&iofs->IOFS.io_Message);
  1507.         }else
  1508.         {
  1509.         rambase->iofs=NULL;
  1510.         Signal(1,0);
  1511.         }
  1512.     }
  1513. #endif
  1514.     Wait(1<<rambase->port->mp_SigBit);
  1515.     }
  1516. }
  1517.  
  1518. const char end=0;
  1519.